#include <QSqlError>
#include "tools/Gadget.h"

QList<QString> Extend::CombinationColumn(QVariant attribute, QVariant destination) {
    QList<QString> resultli; //** 结果收集
    std::string letter; //** 过程产出定义
    char st = 'A';
    char ed = 'Z';
    int lenght = 0;
    int strlen = 0;
    int endlen = 0;
    std::string stoplace;
    QString tridata = attribute.toString().toUpper();
    QString enddata = destination.toString().toUpper();;
    if (Extend::isInt(tridata) && Extend::isInt(enddata)) //** 如果参数为 数字 + 数字
    {
        strlen = attribute.toInt();
        endlen = destination.toInt();
        if (endlen - strlen > 0)
        {
            lenght = endlen;
        }
        else
        {
            lenght = strlen + endlen;
        }
        for (int r = 0; r < strlen; r++) letter += st;
        for (int r = 0; r < strlen + lenght; r++) stoplace += ed;
    }
    else if (Extend::isInt(tridata) && !Extend::isInt(enddata)) //** 如果参数为 数字 + 字符串
    {
        strlen = attribute.toInt();
        if (QRegularExpression("[a-zA-Z]+").match(enddata).capturedTexts().join("").size() == enddata.size())
        {
            if (tridata.toUInt() <= (uint)enddata.size()) //** 区分 attr 参数为 NULL 的情况。当 attr 参数为 NULL 时， strlen 为 0，因此不适合使用保底 lenght 进行累加
            {
                lenght = enddata.size();
                stoplace = enddata.toStdString();
            }
            else
            {
                lenght = enddata.size() + tridata.toUInt();
            }

        }
        for (int r = 0; r < strlen; r++) letter += st;
        if (!stoplace.size()) for (int r = 0; r < strlen + lenght; r++) stoplace += ed;
    }
    else if (!Extend::isInt(tridata) && !Extend::isInt(enddata)) //** 如果参数为 字符串 + 字符串
    {
        int strstore = 0;
        int endstore = 0;
        bool strstate = QRegularExpression("[a-zA-Z]+").match(tridata).capturedTexts().join("").size() == tridata.size();
        bool endstate = QRegularExpression("[a-zA-Z]+").match(enddata).capturedTexts().join("").size() == enddata.size();
        if (strstate) for (int i = 0; i < tridata.size(); i++) strstore += (int)tridata[i].toLatin1();
        if (endstate) for (int i = 0; i < enddata.size(); i++) endstore += (int)enddata[i].toLatin1();
        if (strstate && endstate)
        {
            if (enddata.size() >= tridata.size() && strstore < endstore) //** 已通过符合以上判断，此条件成立，则 destin 参数是 attr 参数的未来位
            {
                strlen = tridata.size();
                endlen = enddata.size();
                lenght = endlen;
                letter = tridata.toStdString();
                stoplace = enddata.toStdString();
            }
            else //** 如果 destin 参数不是 attr 的未来位，则将使用 destin 参数的位数作为增加位进行计算
            {
                strlen = tridata.size();
                endlen = enddata.size();
                if (endlen)
                {
                    lenght = endlen + strlen;
                }
                letter = tridata.toStdString();
            }
            if (strstore == (int)ed * tridata.size())
            {
                resultli.append(letter.data());
            }
        }
        else if (!strstate && endstate)
        {
            strlen = tridata.size();
            endlen = enddata.size();
            int strstore = tridata.size() * (int)st;
            if (enddata.size() >= tridata.size() && strstore < endstore)
            {
                if (endlen) lenght = endlen;
                stoplace = enddata.toStdString();
            }
            else
            {
                if (endlen) lenght = strlen + endlen;
            }
            for (int r = 0; r < strlen; r++) letter += st;
        }
        else //** 如果 destin 参数不是 attr 的未来位，并且 attr 不符合条件，则使用初始值和 destin 参数的位数作为增加位进行计算
        {
            strlen = tridata.size();
            endlen = enddata.size();
            if (endlen)
            {
                lenght = endlen + strlen;
            }
            for (int r = 0; r < strlen; r++) letter += st;
        }
        if (!stoplace.size()) for (int r = 0; r < lenght; r++) stoplace += ed;
    }
    else if (!Extend::isInt(tridata) && Extend::isInt(enddata)) //** 如果参数为 字符串 + 数字
    {
        strlen = tridata.size();
        int endstore = destination.toUInt() * (int)ed;
        if (QRegularExpression("[a-zA-Z]+").match(tridata).capturedTexts().join("").size() == tridata.size())
        {
            int strstore = 0;
            for (int i = 0; i < strlen; i++) strstore += (int)tridata[i].toLatin1();
            qDebug() << ((size_t)strlen <= destination.toUInt()) << strstore << endstore << 889;
            if ((size_t)strlen <= destination.toUInt() && strstore < endstore)
            {
                lenght = destination.toUInt();
            }
            else
            {
                lenght = strlen + destination.toUInt();
            }
            letter = tridata.toStdString();
            if (strstore == (int)ed * tridata.size())
            {
                resultli.append(letter.data());
            }
        }
        else
        {
            int strstore = tridata.toUInt() * (int)st;
            if ((size_t)strlen <= destination.toUInt() && strstore < endstore)
            {
                lenght = destination.toUInt();
            }
            else
            {
                lenght = strlen + destination.toUInt();
            }
            for (int r = 0; r < strlen; r++) letter += st;
        }
        if (!stoplace.size()) for (int r = 0; r < lenght; r++) stoplace += ed;
    }
    else
    {
        resultli.append("<< support arguments >> \n letter + place || start place + end place || letter + letter || str + pass place");
    }
    for (int place = 0; place < lenght; place++) //** 循环预期位数
    {
        if (strlen)
        {
            strlen = 0;
            place = letter.size() - 1;
        }
        else
        {
            letter += st; //** 累计位数，从一位数开始累计，依次增加
        }
        int recoilg_index = place - 1; //** 前一位数，用于特殊判断
        int atnstore = (int)ed - (int)st; //** 预期分差
        int allstore = (place + 1) * (int)ed; //** 预期总分
        int store = 0; //** 当前位数成绩
        bool raiders = false;
        while (true)
        {
            if (letter[place] < ed) //** 如果当前位数索引末尾未完成循环, 并且没有特赦、或者特赦了但是数据为空的，可以执行循环
            {
                while (true) //** 重复检查
                {
                    resultli.append(letter.data()); //将最初的，未特殊加工的数据以及加工的数据装入结果列表
                    if (stoplace.size() && stoplace == letter)
                    {
                        raiders = true;
                        break;
                    }
                    if (letter[place] == ed) //** 如果当前位数索引末尾已完成循环
                    {
                        if (recoilg_index >= 0) //** 如果前一位索引大于等于0，等同 place 至少大于等于1，意味着存在前一位数据
                        {
                            if (letter[recoilg_index] < ed) //** 如果前一位数据未完成循环
                            {
                                letter[recoilg_index]++; //** 累加
                            }
                        }
                        letter[place] = st; //** 最后一位数据已完成循环，将它置为初始值，以再次通过 if (letter[place] < ed) 循环
                        if (recoilg_index > 0) //** 如果前一位索引大于0，则意味着 recoilg_index 至少为1，那么 place 至少为 2，即当前数据至少为 3 位数据， 那么走以下判断
                        {
                            for(int p = 0; p <= recoilg_index; p++) //** 从0循环至前一位数据，包括前一位索引，此操作对0 - 前一位索引 的所有值有效
                            {
                                /* 如果存在索引已完成循环，并且该索引前一位未完成循环，并且p值大于0，并且符合 letter[p] 和 letter[p - 1] < ed 条件的数据在结果列表中 */
                                if (letter[p] == ed && letter[p - 1] < ed && p && resultli.contains(letter.data()))
                                {
                                    letter[p] = st; //** 那么则将 p 索引数据置为初始值
                                    letter[p - 1]++; //** 那么则将 p-1 索引数据累+1
                                }
                            }
                        }
                        break; //** 组后一位数据产生的变动已处理完毕，结束当前循环
                    }
                    else
                    {
                        letter[place] ++; //** 如果当前位数索引末尾未完成循环，那么数据累计+1
                    }
                }
            }
            for (char i : letter) store += int(i); //** 统计分数
            /*
                1. 条件1-> 针对于已经完成循环后，当前位数最后一位重置，分数不符合 size * (int)ed 的情况，因此需要补差值 atnstore 以使该情况合理
                2. 条件2-> 针对于满足停止条件的情况，满足条件则获得特赦标志，跳出该循环
                3. 条件3-> 针对于无法进入 if (letter[place] < ed 条件的数据，即ed结尾，这类数据在循环之前已做了添加至结果集的操作，那么则直接判断分数和结果集情况是否符合预期
                4. 条件4-> 针对于字符满足 if (letter[place] == ed) 条件后，前一位++，最后一位重置，则会存在 ZZA的情况，则此时以下条件种，第四条件通过的情况，因此需要判断ZA是否在
                          结果集种，不存在结果中则通过 if (letter[place] < ed 走一次满循环
            */
            if (((store + atnstore) == allstore && place == 0) || raiders ||
                 (allstore == store && resultli.contains(letter.data()) && resultli.size() == 1) ||
                ((store + atnstore) == allstore && place > 0 && resultli.contains(letter.data())))
            {
                for(size_t p = 0; p < letter.size(); p++) letter[p] = st; //** 初始化字符，通过以上判断意味着当前累加的位数数据均已完成全部循环
                break;
            }
            else
            {
                store = 0; //** 不符合条件重置分数
            }
        }
    }
    return resultli;
}

void Extend::ColExtendToMapInt(QMap<int, QString> &object, int bring){
    QList<QString> cols = CombinationColumn(NULL, bring);
    int index = 0;
    for (QString col : cols)
    {
        object[index] = col;
        index++;
    }
}

void Extend::ColExtendToMapStr(QMap<QString, int> &object, int bring){
    QList<QString> cols = CombinationColumn(NULL, bring);
    int index = 0;
    for (QString col : cols)
    {
        object[col] = index;
        index++;
    }
}

void Extend::ColExtendToList(QStringList &Object, int bring){
    int arraylen = AlphaArray().size();
    QList<QString> array = AlphaArray();
    bool _terminate = false;
    int addcount = 0;
    std::string Ocobj;
    for (int index = 0; index <= arraylen; index++){
        if (_terminate){
            break;
        }
        else{
            for (int reindex = 0; reindex < arraylen; reindex++){
                if (addcount == bring){
                    _terminate = true;
                    break;
                }
                else if (addcount + 1 <= arraylen){
                    Object.append(array[reindex].toStdString().data());

                }else{
                    std::stringstream stream;
                    stream << array[index - 1].toStdString().data();
                    stream << array[reindex].toStdString().data();
                    Ocobj = stream.str();
                    Object.append(Ocobj.c_str());
                }
                addcount++;
            }
        }
    }
}

QMap<QString, QList<QString>> Extend::SuperQuery(QSqlDatabase* db, QString tabname, QString fillQuery){
    QRegularExpression sql_request_regexpr("\\((.*)\\)");
    QMap<QString, QList<QString>> sql_request_result;
    QList<QString> sql_result_struct;
    QString sql_tabquery = "SELECT * FROM sqlite_master WHERE type = 'table' and name='%1'";
    QSqlQuery query(*db);
    query.exec(sql_tabquery.arg(tabname));
    while (query.next())
    {
        int master_count = query.record().count();
        for (int index = 0; index < master_count; index++)
        {
            sql_result_struct.clear();
            QString struct_value = query.value(index).toString().simplified();
            if (!struct_value.isEmpty())
            {
                QRegularExpressionMatch struct_value_extract = sql_request_regexpr.match(struct_value);
                if (struct_value_extract.hasMatch())
                {
                    QList<QString> field = struct_value_extract.captured(1).split(",");
                    for (auto col = 0; col < field.size(); col++)
                    {
                        sql_result_struct.append(field[col].simplified().split(QRegularExpression("\\s+")).first());
                    }
                }
            }
        }
   }
   if (!sql_result_struct.isEmpty())
   {
       QString sql_unicldcondition = "SELECT * FROM %1;";
       QString sql_icldcondition = "SELECT * FROM %1 WHERE %2;";
       if (!fillQuery.isEmpty())
       {
           query.exec(sql_icldcondition.arg(tabname, fillQuery));
       } else {
           query.exec(sql_unicldcondition.arg(tabname));
       }
       while (query.next())
       {
           for (int i = 0; i < sql_result_struct.size(); i++)
           {
               sql_request_result[sql_result_struct[i]].append(query.value(sql_result_struct[i]).toString());
           }
        }
       if (!sql_request_result.isEmpty()) sql_request_result["tab-struct"] = sql_result_struct;
    }
    sql_request_result["sql"] = {query.executedQuery()};
    return sql_request_result;
}

bool Extend::BoolAssert(QString Bool){
    if ( Bool.size() == 4 &&
         Bool.compare("true", Qt::CaseInsensitive) == 0 ){
        return true;
    } else if ( Bool.size() == 5 &&
                Bool.compare("false", Qt::CaseInsensitive) == 0 ){
        return false;
    } else {
        return -1;
    }
}

QStringList Extend::getGlobalMatching(QString Sc, QString regexp){
    QStringList ResultList;
    QRegularExpression reg(regexp);
    QRegularExpressionMatchIterator Match = reg.globalMatch(Sc);
    while (Match.hasNext()) {
        QStringList CapText = Match.next().capturedTexts();
        if (!CapText.isEmpty()){
            foreach(QString Item, CapText){
                if (Item.isEmpty()){
                    continue;
                } else ResultList.append(Item);
            }
        }
    }
    return ResultList;
}

QStringList Extend::getGlobalMatching(QString Sc, QRegularExpression regexp){
    QStringList ResultList;
    QRegularExpressionMatchIterator Match = regexp.globalMatch(Sc);
    while (Match.hasNext()) {
        QStringList CapText = Match.next().capturedTexts();
        if (!CapText.isEmpty()){
            foreach(QString Item, CapText){
                if (Item.isEmpty()){
                    continue;
                } else ResultList.append(Item);
            }
        }
    }
    return ResultList;
}

QMap<QString, QString> Extend::getGlobalMatchingSec(QString Sc, QString regexp, uint skewing){
    QMap<QString, QString> ResultMap;
    QRegularExpressionMatchIterator Match = QRegularExpression(regexp).globalMatch(Sc);
    uint count = 0;
    QList<uint> indexList;
    QString lastKey;
    while (Match.hasNext())
    {
        QRegularExpressionMatch matchIt = Match.next();
        uint CapStart = matchIt.capturedStart();
        QString CapText = matchIt.capturedTexts().join("");
        if (count)
        {
            ResultMap.insert(lastKey, Sc.mid(indexList[count - 1] + skewing, CapStart - indexList[count - 1] + skewing));
        }
        count++;
        indexList.append(CapStart);
        lastKey = CapText;
    }
    ResultMap.insert(lastKey, Sc.mid(indexList[count - 1] + skewing));
    return ResultMap;
}

QMap<QString, QString> Extend::getGlobalMatchingSec(QString Sc, QString regexp, QString skewing){
    QMap<QString, QString> ResultMap;
    QRegularExpressionMatchIterator Match = QRegularExpression(regexp).globalMatch(Sc);
    uint count = 0;
    QList<uint> indexList;
    QString lastKey;
    while (Match.hasNext())
    {
        QRegularExpressionMatch matchIt = Match.next();
        uint CapStart = matchIt.capturedStart();
        QString CapText = matchIt.capturedTexts().join("");
        if (count)
        {
            uint interiorIndex = 0;
            QString midString = Sc.mid(indexList[count - 1], CapStart - indexList[count - 1]);
            if (midString.contains(skewing)) interiorIndex = midString.indexOf(skewing) + 1;
            ResultMap.insert(lastKey, midString.mid(interiorIndex));
        }
        count++;
        indexList.append(CapStart);
        lastKey = CapText;
    }
    uint interiorIndex = 0;
    QString midString = Sc.mid(indexList[count - 1], -1);
    if (midString.contains(skewing)) interiorIndex = midString.indexOf(skewing) + 1;
    ResultMap.insert(lastKey, midString.mid(interiorIndex));
    return ResultMap;
}

//# 依次递进-路径提取
QStringList Extend::ExtractPath(QString LongChar, QString primaryReg, QString secondaryReg, QStringList Suffix){
    QString SimpleChar = LongChar.simplified().replace('\\', '/').remove("\n");
    QStringList CollectPath;
    QRegularExpression RegT(primaryReg);
    QRegularExpression Reg(secondaryReg);
    QStringList getRegrsList = getGlobalMatching(SimpleChar, RegT);
    foreach(QString it, getRegrsList)
    {
        int dindex = it.lastIndexOf(".") - 1;
        int looseRange = it.size() - dindex;
        for(int i = 0; i < looseRange; i++)
        {
            QString unvalidPath = it.mid(0, dindex + i);
            QFileInfo File(unvalidPath);
            if (File.isFile())
            {
                if (Suffix.isEmpty())
                {
                    CollectPath << unvalidPath;
                }
                else
                {
                    if (Suffix.contains(File.suffix()))
                    {
                        CollectPath << unvalidPath;
                    }
                }
                SimpleChar.remove(it);
                break;
            }
        }
    }
    if (Suffix.isEmpty() || Suffix.indexOf(""))
    {
        QStringList getUnsuffixList = getGlobalMatching(SimpleChar, Reg);
        getUnsuffixList.removeDuplicates();
        foreach(QString sp, getUnsuffixList)
        {
            SimpleChar = SimpleChar.replace(sp, "&&" + sp);
        }
        foreach(QString lst, SimpleChar.split("&&"))
        {
            if (lst.indexOf(Reg) != -1)
            {
                int expectIndex = lst.lastIndexOf(QRegularExpression("[\\\\|/]"));
                int looseRange = lst.size() - expectIndex;
                for(int i = 0; i < looseRange; i++)
                {
                    QString unvalidPath = lst.mid(0, expectIndex + i);
                    QFileInfo File(unvalidPath);
                    if (File.isFile())
                    {
                        CollectPath << unvalidPath;
                        SimpleChar.remove(lst);
                        break;
                    }
                }
            }
        }
    }
    CollectPath.removeDuplicates();
    return CollectPath;
}

qint64 Extend::Getrandom(qint64 min, qint64 max){
    return min + rand() % (max + 1 - min);
}

qint64 Extend::Min(QList<qint64> _T){
    qint64 CS = _T.first();
    foreach(qint64 ele, _T){if (ele < CS) CS = ele;}
    return CS;
}

qint64 Extend::Min(QList<int> _T){
    int CS = _T.first();
    foreach(int ele, _T){if (ele < CS) CS = ele;}
    return CS;
}

qint64 Extend::Max(QList<qint64> _T){
    qint64 CS = _T.first();
    foreach(qint64 ele, _T){if (ele > CS) CS = ele;}
    return CS;
}

qint64 Extend::Max(QList<int> _T){
    int CS = _T.first();
    foreach(int ele, _T){if (ele > CS) CS = ele;}
    return CS;
}

QVariant Extend::Min(QList<QString> _T, bool isSizeMode){
    qint64 CS = _T.first().size();
    QString first = _T.first();
    foreach(QString ele, _T)
    {
        if (ele.size() < CS)
        {
            CS = ele.size();
            first.swap(ele);
        }
    }
    if (isSizeMode)
    {
        return CS;
    }
    else
    {
        return first;
    }
}

QVariant Extend::Max(QList<QString> _T, bool isSizeMode){
    int CS = _T.first().size();
    QString first = _T.first();
    foreach(QString ele, _T)
    {
        if (ele.size() > CS)
        {
            CS = ele.size();
            first.swap(ele);
        }
    }
    if (isSizeMode)
    {
        return CS;
    }
    else
    {
        return first;
    }
}

void Extend::orderBy(QList<qint64> &_sc, bool reverse){
    QList<qint64> dt;
    int size = 0;
    int maxItem;
    const qint64 globalsize = _sc.size();
    while (size < globalsize)
    {
        reverse ? maxItem = Min(_sc) : maxItem = Max(_sc);
        _sc.removeAt(_sc.indexOf(maxItem));
        dt.insert(0, maxItem);
        size++;
    }
    _sc.swap(dt);
}

void Extend::orderBy(QList<int> &_sc, bool reverse){
    QList<int> dt;
    int size = 0;
    int maxItem;
    const int globalsize = _sc.size();
    while (size < globalsize)
    {
        reverse ? maxItem = Min(_sc) : maxItem = Max(_sc);
        _sc.removeAt(_sc.indexOf(maxItem));
        dt.insert(0, maxItem);
        size++;
    }
    _sc.swap(dt);
}

std::string Extend::dbCstr(double cs, dbCstrMD mode, int retain){
    std:: string dbcchar;
    std::string Decimals;
    std::stringstream stream;
    int specidx;
    int DecimalsPlace;
    int integet = std::to_string((int)cs).size();
    int size = integet + retain + 1;
    bool fill;
    char *cschar = new char[size];
    _gcvt_s(cschar, sizeof (cschar), cs, size);
    dbcchar = cschar;
    specidx = dbcchar.find_last_of(".");
    Decimals = dbcchar.substr(specidx + 1, -1);
    DecimalsPlace = retain - (int)Decimals.size();
    if (mode == dbCstrMD::Absolute){
        stream << cschar;
        fill = true;
    } else {
        if (DecimalsPlace == retain){
            stream << dbcchar.substr(0, specidx);
            fill = false;
        } else {
            stream << cschar;
            fill = true;
        }
    }
    delete []cschar;
    if (fill){
        for (int bt = 0; bt < DecimalsPlace; bt++){
            stream << "0";
        }
    }
    return stream.str();
}

QStringList Extend::canonicalPath(QStringList Source, QStringList Suffixs){
    QStringList Gather;
    QFileInfo File;
    if (!Source.isEmpty()){
        foreach(QString Path, Source){
            File = QFileInfo(Path);
            QString Suffix = File.suffix();
            QString canonicalPath = File.canonicalPath();
            if (!Suffixs.isEmpty())
            {
                if (Suffixs.contains(Suffix, Qt::CaseInsensitive) && !Gather.contains(canonicalPath))
                {
                    Gather.append(canonicalPath);
                }
                else
                {
                    continue;
                }
            }
            else
            {
                if (!Gather.contains(canonicalPath)) Gather.append(canonicalPath);
            }
        }
    }
    return Gather;
}

QString Extend::c_tuple(QList<QString> Arg){
    QString last = "(%1)";
    QStringList temporarys;
    foreach(QString I, Arg) temporarys.append(QString("'%1'").arg(I));
    return last.arg(temporarys.join(","));
}

QString Extend::c_tuple(QList<int> Arg){
    QString last = "(%1)";
    QStringList temporarys;
    foreach(int I, Arg) temporarys.append(QString("'%1'").arg(I));
    return last.arg(temporarys.join(","));
}

QString Extend::c_tuple(QList<bool> Arg){
    QString last = "(%1)";
    QStringList temporarys;
    foreach(bool I, Arg) temporarys.append(QString("'%1'").arg(I));
    return last.arg(temporarys.join(","));
}

QMap<QString, QString> Extend::QssAttributeForMap(QString Qss, QString PrimaryAttri, QString ValueFilter){
    QMap<QString, QString> AttriMap;
    QString Expression = QString("%1\{(.*?)}").arg(PrimaryAttri.toLower());
    QRegularExpressionMatch Match = QRegularExpression(Expression).match(Qss.toLower());
    QString ChildQssChar = Match.captured(Match.lastCapturedIndex());
    QStringList SplitChildQssChar = ChildQssChar.split(";");
    foreach(QString line, SplitChildQssChar) {
        if (!line.trimmed().isEmpty()){
            QStringList SplitLine = line.split(":");
            QString key = SplitLine[0].trimmed();
            QString value = SplitLine[1].trimmed();
            if (ValueFilter.isEmpty()){
                AttriMap.insert(key, value);
            } else {
                if (!QRegularExpression(ValueFilter).match(value).capturedTexts().isEmpty()){
                    AttriMap.insert(key, value.replace(ValueFilter,""));
                } else {
                    AttriMap.insert(key, value);
                }
            }
        }
    }
    return AttriMap;
}

QString Extend::QssAttributeValueSwap(QString Qss, QStringList PrimaryAttri, QList<QList<QString>> ChildKeys, QList<QList<QString>> ReplaceValues){
    QString styleSheet = Qss;
    int keyNum = ChildKeys.size();
    int valueNum = ReplaceValues.size();
    if (keyNum > valueNum) for(int i = 0; i < (keyNum - valueNum); i++) ReplaceValues.append({""});
    for(int index = 0; index < PrimaryAttri.size(); index++)
    {
        styleSheet = QssAttributeValueSwapBase(styleSheet, PrimaryAttri[index], ChildKeys[index], ReplaceValues[index]);
    }
    return styleSheet;
}

QString Extend::QssAttributeValueSwap(QString Qss, QString PrimaryAttri, QStringList ChildKeys, QStringList ReplaceValues){
    QString styleSheet = Qss;
    styleSheet = QssAttributeValueSwapBase(styleSheet, PrimaryAttri, ChildKeys, ReplaceValues);
    return styleSheet;
}

QString Extend::QssAttributeValueSwap(QString Qss, QStringList PrimaryAttri, QString ChildKeys, QString ReplaceValues){
    QString styleSheet = Qss;
    for(int index = 0; index < PrimaryAttri.size(); index++)
    {
        styleSheet = QssAttributeValueSwapBase(styleSheet, PrimaryAttri[index], {ChildKeys}, {ReplaceValues});
    }
    return styleSheet;
}

QString Extend::QssAttributeValueSwapBase(QString Qss, QString PrimaryAttri, QStringList ChildKeys, QStringList ReplaceValues){
    QString styleSheet = Qss;
    QString Expression = QString("%1\{(.*?)}").arg(PrimaryAttri);
    QRegularExpressionMatch Match = QRegularExpression(Expression).match(Qss);
    if (Match.hasMatch())
    {
        QString ChildQssChar = Match.captured(0);
        QString RightCopyQssChar = ChildQssChar;
        int index = 1;
        foreach(QString key, ChildKeys)
        {
            QStringList MatchList = QRegularExpression(QString("%1\\s*:(\\s*.*?);").arg(key)).match(ChildQssChar).capturedTexts();
            if (!MatchList.isEmpty())
            {
                QString allString = MatchList.first();
                QString valueString = MatchList.last();
                QString replaceValue;
                if (ReplaceValues.size() >= index)
                {
                    replaceValue = ReplaceValues[index -1];
                }
                else
                {
                    replaceValue = "";
                }

                QString replaceTarget = MatchList.first().replace(valueString, replaceValue);
                RightCopyQssChar = RightCopyQssChar.replace(allString, replaceTarget);
                index++;
            }
        }
        styleSheet = styleSheet.replace(ChildQssChar, RightCopyQssChar);
    }
    return styleSheet;
}

QString Extend::g_plyduration(QVariant time){
    QJsonArray Array;
    QString datatime = time.toString();
    QMap<QString, qint64> timeMap({{"hour", 3600000},
                                {"minute", 60000},
                                {"second", 1000},
                                {"msecond", 1}});
    QList<qint64> relationValue = timeMap.values();
    orderBy(relationValue, true);
    int relationsize = relationValue.length();
    if (QRegularExpression("\\d+\\W+").match(datatime).hasMatch()){

        QList<QString> totaldata = datatime.split(QRegularExpression("\\W"));
        int totalsize = totaldata.size();
        int totalmsec = 0;
        if (totalsize == 2) relationValue = relationValue.mid(relationsize - totaldata.length());
        for (int place=0; place < totalsize; place++)
        {
            totalmsec += totaldata[place].toInt() * relationValue[place];
        }
        return QString::number(totalmsec);
    } else {
        int totaltime = datatime.toInt();
        int hour = floor(totaltime / timeMap["hour"]);
        int minute = floor(totaltime - hour * timeMap["hour"]) / timeMap["minute"];
        int second = (totaltime - hour * timeMap["hour"] - minute * timeMap["minute"]) / timeMap["second"];
        int msecond = totaltime - hour * timeMap["hour"] - minute * timeMap["minute"] - second * timeMap["second"];
        QList<QString> result;
        result << QString::number(minute).rightJustified(2, '0')
               << QString::number(second).rightJustified(2, '0')
               << QString::number(msecond).rightJustified(3, '0');
        if (hour) result.insert(0, QString::number(hour));
        return result.join(":");
    }
}

QString Extend::SuperConver(QString itsr, cvType Type, char spc){
    std::stringstream gatherStream;
    QList<QString> array = AlphaArray();
    std::string itsrchar = itsr.toStdString();
    char spchar = ' ';
    int indfin = QString(spc).indexOf(QRegularExpression(".+"));
    if (indfin != -1) spchar = spc;
    switch (Type) {
        case cd_Ascii:
            for(size_t i = 0; i < itsrchar.size(); i++){
                gatherStream << (int)itsrchar[i];
                if (i + 1 < itsrchar.size()) gatherStream << array[Getrandom(0, array.size() - 1)].toStdString() << spchar;
            }
            break;
        case cd_String:
            QStringList asciiList = itsr.split(QRegularExpression("\\s+"));
            for(int i = 0; i < asciiList.size(); i++){
                std::string cv = asciiList[i].remove(QRegularExpression("[^\\d]")).toStdString();
                gatherStream << (char) stoi(cv);
            }
            break;
    }
    QString cvrs = gatherStream.str().data();
    return cvrs;
}

void Extend::wcormbc(wchar_t *w_char, char *_mbchar, bool reverser){
    if (reverser){
        size_t ctsize = mbstowcs(NULL, _mbchar, 0) + 1;
        mbstowcs(w_char, _mbchar, ctsize);
    } else {
        size_t ctsize = wcstombs(NULL, w_char, 0) + 1;
        wcstombs(_mbchar, w_char, ctsize);
    }
}

void Extend::wcormbc(wchar_t *w_char, const char *_mbchar){
    size_t ctsize = mbstowcs(NULL, _mbchar, 0) + 1;
    mbstowcs(w_char, _mbchar, ctsize);
}

void Extend::wcormbc(const wchar_t *w_char, char *_mbchar){
    size_t ctsize = wcstombs(NULL, w_char, 0) + 1;
    wcstombs(_mbchar, w_char, ctsize);
}

QByteArray Extend::getImgbyte(QVariant push){
    QPixmap pixmap;
    if (push.metaType().id() == QMetaType::QString)
    {
        pixmap.load(push.toString());
    }
    else
    {
        pixmap = push.value<QPixmap>();
    }
    QByteArray bytesArray;
    QBuffer Buffer(&bytesArray);
    Buffer.open(QIODevice::WriteOnly);
    pixmap.save(&Buffer, "png", 100);
    return bytesArray.toBase64();
}

QString Extend::rectInfoProduction(char L_wall, char T_wall, char R_wall, char B_wall, char emptyFill, int L_tab,  QStringList &content, QFont &contentFont){
    QList<qint64> horizontalWidthList;
    QFontMetrics spFont(contentFont);
    QString logAngularSpinfo;
    QString tab = QString("").rightJustified(L_tab, '\t');
    QString justifyFormat = tab + "%1\n";
    QString centraFormat = tab + L_wall + " %1 %2\n";
    foreach(QString line, content)
    {
        horizontalWidthList.append(spFont.horizontalAdvance(line.toLatin1()) / 6 + 4);
    }
    int maxLenght = Max(horizontalWidthList);
    QString TopFormat = justifyFormat.arg(QString("").leftJustified(maxLenght, T_wall));
    QString DownFormat = justifyFormat.arg(QString("").leftJustified(maxLenght, B_wall));
    foreach(QString line, content)
    {
        //#左右特殊字符填充损耗2，空格损耗2
        line = line.leftJustified(maxLenght - 4, emptyFill);
        logAngularSpinfo += centraFormat.arg(line, QString(R_wall));
    }
    logAngularSpinfo = "\n" + TopFormat + logAngularSpinfo + DownFormat;
    return logAngularSpinfo;
}

int Extend::lineDistance(QPoint &point1, QPoint &point2){
    int x1 = point1.x();
    int y1 = point1.y();
    int x2 = point2.x();
    int y2 = point2.y();
    return sqrt(ceil(pow(abs(x1 - x2), 2)) + ceil(pow(abs(y1 - y2), 2)));
}

QPair<int, int> Extend::parallelx(QPoint &point1, int &point2_y, int radius){
    int x1 = point1.x();
    int y1 = point1.y();
    int spand = y1 - point2_y;
    int xe = x1 - sqrt(pow(radius, 2) - pow(spand, 2));
    int xt = x1 + sqrt(pow(radius, 2) - pow(spand, 2));
    return qMakePair(xe, xt);
}

QPair<int, int> Extend::parallely(QPoint &point1, int &point2_x, int radius){
    int x1 = point1.x();
    int y1 = point1.y();
    int spand = x1 - point2_x;
    int ye = y1 - sqrt(pow(radius, 2) - pow(spand, 2));
    int yt = y1 + sqrt(pow(radius, 2) - pow(spand, 2));
    return qMakePair(ye, yt);
}

void Extend::getMatchingItem(QRegularExpression expr, QString _targrt, QString &_receive, int expectIndex){
    QList<QString> matchList = expr.match(_targrt).capturedTexts();
    if (matchList.isEmpty())
    {
        _receive = "";
    }
    else
    {
        if (expectIndex <= matchList.size() && expectIndex > 0)
        {
            _receive.swap(matchList[expectIndex - 1]);
        }
        else if (expectIndex == -1)
        {
            QString variant = Max(matchList, false).toString();
            _receive.swap(variant);
        }
        else
        {
            _receive.swap(matchList.first());
        }
    }
}

void Extend::getMatchingItem(QList<QString> exprList, QString _targrt, QString &_receive, QList<int> expectIndex){
    int c = 0;
    for(int how = 0; how < (exprList.size() - expectIndex.size()); how++) expectIndex.append(1);
    foreach(QString expr, exprList)
    {
        QString j;
        getMatchingItem(QRegularExpression(expr), _targrt, j, expectIndex[c]);
        _receive.append(j);
        c++;
    }
}

QString Extend::_date_time(Leave leave, QString problem){
    QMap<int, QString> converConsult;
    QString letter;
    QString defdate;
    QList<QString> array = AlphaArray();
    switch (leave)
    {
        case Leave::data_msec:
        {
            return QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
        }
        case Leave::data_letter:
            defdate = QDateTime::currentDateTime().toString("yyyyMMdd");
            for(int i = 0; i < 10; i++)
            {
                converConsult[i] = QString::fromStdString(array[i].toStdString());
            }
            if (problem.isEmpty())
            {
                foreach(QChar i, defdate)
                {
                    letter += converConsult[QString(i).toInt()];
                }
                return letter;
            }
            else
            {
                foreach(QChar i, problem)
                {

                    letter += QString::number(converConsult.key(i));
                }
                return letter;
            }

        case Leave::data_sec:
        {
            return QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
        }
        case Leave::data_minute:
        {
            return QDateTime::currentDateTime().toString("yyyyMMddhhmm");
        }
        case Leave::data_hour:
        {
            return QDateTime::currentDateTime().toString("yyyyMMddhh");
        }
        case Leave::data_day:
        {
            return QDateTime::currentDateTime().toString("yyyyMMdd");
        }
        case Leave::data_month:
        {
            return QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
        }
        default:
            return QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");

    }
}

QString Extend::join(QList<QString> &list, QString softshell, QString specing){
    QString rsult;
    if (!softshell.contains(QRegularExpression("%\\d+"))) softshell="%1";
    for(int n = 0; n < list.size(); n ++)
    {
        if (n != list.size() - 1)
        {
            rsult += softshell.arg(list[n]) + specing;
        }
        else
        {
            rsult += softshell.arg(list[n]);
        }
    }
    return rsult;
}

bool Extend::isInt(QString _s){
    QRegularExpression uintReg("\\d+");
    QString find_d = uintReg.match(_s).capturedTexts().join("");
    if (find_d.size() == _s.size())
    {
        return true;
    }
    else if (_s.remove(find_d) == '-')
    {
        return true;
    }
    else
    {
        return false;
    }
}

QList<bool> Extend::isBoolli(QStringList li){
    QList<bool> bli;
    foreach(QString i , li)
    {
        if (isInt(i))
        {
            bli.append(static_cast<bool>(i.toUInt()));
        }
        else
        {
            bli.append(false);
        }
    }
    return bli;
}

QList<QString> Extend::isStrli(QList<qint64> li){
    QList<QString> bli;
    foreach(qint64 i , li)
    {
        bli.append(QString::number(i));
    }
    return bli;
}

QList<QString> Extend::isStrli(QList<bool> li){
    QList<QString> bli;
    foreach(bool i , li)
    {
        bli.append(QString::number(i));
    }
    return bli;
}

QList<int> Extend::isIntli(QList<QString> li){
    QList<int> bli;
    foreach(QString i, li)
    {
        if (isInt(i))
        {
            bli.append(i.toUInt());
        }
        else
        {
            bli.append(-1);
        }
    }
    return bli;
}

void Extend::batchFont(QList<QWidget *> source, QFont &font, uint psize){
    font.setPointSize(psize);
    foreach(QWidget *wid, source)
    {
        wid->setFont(font);
    }
}

void Extend::batchFont(QList<QWidget *> source, QFont &font, QString family){
    font.setFamily(family);
    foreach(QWidget *wid, source)
    {
        wid->setFont(font);
    }
}

void Extend::batchFont(QList<QWidget *> source, QFont &font, QFont swap){
    font.swap(swap);
    foreach(QWidget *wid, source)
    {
        wid->setFont(font);
    }
}

QVariant Extend::regeditVist(HKEY mstream, QString Pkey, QString Ckey){
    /*PHKEY hKey：输入参数，表示当前打开或者以下预定义的键，如HKEY_CLASSES_ROOT、HKEY_CURRENT_USER等 。
      LPCWSTR lpSubKey：输入参数，指向一个以null结尾的字符串，包含要打开的注册表子项的名称。如果为空，则打开hKey参数标识的键的新句柄 。
      WORD ulOptions：保留，必须设置为0 。
      REGSAM samDesired：输入参数，表示对指定键希望得到的访问权限的访问标记，可以是多个值的联合 。
      PHKEY phkResult：输出参数，指向一个变量的指针，该变量接收打开的键的句柄。使用完毕后，应调用RegCloseKey关闭句柄 。*/
    QVariant var;
    DWORD receiveType;
    DWORD dtSize;
    HKEY hKey; // 定义注册表键句柄
    LONG lResult1; // 定义操作结果
    LONG lResult2; // 定义操作结果
    wchar_t *prmrkey = new wchar_t[1024];
    wchar_t *scdrkey = new wchar_t[1024];
    wcormbc(prmrkey, Pkey.toStdString().c_str());
    wcormbc(scdrkey, Ckey.toStdString().c_str());
    lResult1 = RegOpenKeyEx(mstream,
                           prmrkey,
                           0,
                           KEY_QUERY_VALUE, // 指定访问权限
                           &hKey);
    if (lResult1 == ERROR_SUCCESS) {
        // 读取键值
        /* LONG RegQueryValueEx(HKEY hKey,            // 打开的注册表键的句柄
                                LPCTSTR lpValueName,  // 要查询的值的名称，如果为NULL，则查询默认值
                                LPDWORD lpReserved,   // 保留，必须设置为NULL
                                LPDWORD lpType,        // 指向接收值类型的变量的指针
                                LPBYTE lpData,        // 指向接收值数据的缓冲区的指针，如果为NULL，则不返回数据
                                LPDWORD lpcbData      // 指向接收缓冲区大小的变量的指针，以字节为单位
                            );
         *
         * REG_SZ：字符串值。
           REG_EXPAND_SZ：可展开的字符串值，包含环境变量。
           REG_BINARY：二进制数据。
           REG_DWORD： 32位数字。
           REG_DWORD_BIG_ENDIAN： 32位数字（大端字节序）。
           REG_LINK：符号链接。
           REG_MULTI_SZ：多重字符串值。*/

        RegQueryValueEx(hKey,
                       scdrkey,
                       NULL,
                       &receiveType,
                       NULL,
                       &dtSize);

        if (receiveType == REG_BINARY)
        {
            BYTE* byteArray = new BYTE[dtSize];
            lResult2 = RegQueryValueEx(hKey,
                                       scdrkey,
                                       NULL,
                                       &receiveType,
                                       (LPBYTE)byteArray,
                                       &dtSize);
            if (lResult2 == ERROR_SUCCESS) {
                QString result;
                for(int how = 0; how < (int)dtSize; how++) result += QString::number(byteArray[how], 16).leftJustified(2, '0');
                var.setValue(result);
            } else {
                var.setValue(QString("ERROR: ") + QString::number(lResult2));
            }
            delete []byteArray;
        }
        else if (receiveType == REG_SZ)
        {
            TCHAR szBuffer[dtSize];
            char *result = new char[dtSize];
            lResult2 = RegQueryValueEx(hKey,
                                       scdrkey,
                                       NULL,
                                       &receiveType,
                                       (LPBYTE)szBuffer,
                                       &dtSize);
            if (lResult2 == ERROR_SUCCESS) {
                wcormbc(szBuffer, result, false);
                var.setValue(QString(result));
            } else {
                var.setValue(QString("ERROR: ") + QString::number(lResult2));
            }
            delete []result;
        }
        else if (receiveType == REG_DWORD)
        {
            LONG result;
            lResult2 = RegQueryValueEx(hKey,
                                       scdrkey,
                                       NULL,
                                       &receiveType,
                                       (LPBYTE)&result,
                                       &dtSize);
            if (lResult2 == ERROR_SUCCESS) {
                var.setValue(QString::number(result));
            } else {
                var.setValue(QString("ERROR: ") + QString::number(lResult2));
            }
        }

        RegCloseKey(hKey);
    } else {
        var.setValue(QString("PRIMARY OPEN ERROR"));
    }
    delete []prmrkey;
    delete []scdrkey;
    return var;
}

bool Extend::startProcess(QString shellchar){
/*lpApplicationName: 要执行的可执行文件的路径。如果为 NULL，则使用 lpCommandLine 参数中的内容 。
lpCommandLine: 命令行参数，包括可执行文件的路径和其他参数。如果 lpApplicationName 为 NULL，则 lpCommandLine 中的第一个空白分隔的标记被视为可执行文件的名称 。
lpProcessAttributes 和 lpThreadAttributes: 进程和线程的安全性属性，通常设置为 NULL。
bInheritHandles: 决定新进程是否继承父进程的句柄。
dwCreationFlags: 控制新进程的创建方式，如是否创建一个新的控制台。
lpEnvironment: 新进程的环境变量，通常设置为 NULL，使其继承父进程的环境。
lpCurrentDirectory: 新进程的初始工作目录。
lpStartupInfo: 指定了要为新进程创建的主窗口的样式、大小等信息。
lpProcessInformation: 接收有关新进程的信息，如其句柄和标识符
    BOOL CreateProcessW(
    LPCWSTR lpApplicationName,
    LPWSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCWSTR lpCurrentDirectory,
    LPSTARTUPINFOW lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation);*/

    STARTUPINFO stinfo;
    PROCESS_INFORMATION prinfo;

    ZeroMemory(&stinfo, sizeof (stinfo));
    ZeroMemory(&prinfo, sizeof (prinfo));
    stinfo.cb = sizeof (stinfo);
    stinfo.wShowWindow = SW_HIDE;
    std::string data = shellchar.toStdString();
    std::string command = "powershell.exe -Command \"" + data + "\""; //# \ 符号为转义字符，因为左边字符串中，字符包含字符，需要进行转义

    size_t exptSize = mbstowcs(NULL, command.data(), 0);
    wchar_t *wchar = new wchar_t[exptSize];
    wcormbc(wchar, command.data(), true);
    bool runstat = CreateProcessW(NULL, wchar, NULL, NULL, FALSE, 0, NULL, NULL, &stinfo, &prinfo);
    WaitForSingleObject(prinfo.hProcess, INFINITE);
    delete []wchar;
    CloseHandle(prinfo.hProcess);
    CloseHandle(prinfo.hThread);
    return runstat;
}

void Extend::painterLinear(QPainter &painter, QRect offectrect, NT::CST_BRIGHT_SPOT orien, QList<QColor> _colors){
    QLinearGradient lineGrandient;
    double DetailAddtion = 0;
    double RelativeStep = 1.0 / (double)(_colors.size() - 1);
    if (orien == NT::ORIEN_HORIZONTAL)
    {
        lineGrandient = QLinearGradient(0, 0, offectrect.width(), 0);
    }
    else
    {
        lineGrandient = QLinearGradient(0, 0, 0, offectrect.height());
    }
    foreach(QColor color, _colors)
    {
        lineGrandient.setColorAt(DetailAddtion, color);
        lineGrandient.setSpread(QGradient::ReflectSpread);
        DetailAddtion += RelativeStep;
    }
    painter.fillRect(offectrect, lineGrandient);
}

qint64 Extend::g_pix_fl(QVariant pixmap, QSize expsize)
{
    QImage image;
    qint64 hash = 0;
    if (pixmap.metaType().id()  == QMetaType::QPixmap)
    {
        QPixmap p = pixmap.value<QPixmap>();
        if (!p.isNull()) image = p.toImage().scaled(expsize);

    }
    else if (pixmap.metaType().id()  == QMetaType::QImage)
    {
        image = pixmap.value<QImage>().scaled(expsize);
    }
    else if (pixmap.metaType().id()  == QMetaType::QString)
    {
        QPixmap p(pixmap.toString());
        if (!p.isNull()) image = p.toImage().scaled(expsize);
    }
    for(int x = 0; x < image.width();x++)
    {
        for(int y = 0; y < image.width();y++)
        {
            hash += image.pixel(x, y);
            hash += (y >> 2);
            hash ^= (y << 4);
        }
    }
    return hash;
}
